#include "srv_menu.h"

#include "stdio.h"
#include "string.h"
#include "stdint.h"

#include "bsp_delay.h"
#include "srv_lcd.h"
#include "drv_adc_init.h"
#include "common.h"
#include "srv_dino_game.h"

#define TURN_TO    0
#define CONTINUE   1

//枚举菜单函数编号，用于存放在菜单数组中对应位置
typedef enum
{
    Ignore               = 0,   //空
    Main_Menu            = 1,   //主菜单编号
    PowerMeter_Menu      = 2,   //功率计菜单编号
    ExternalVoltage_Menu = 3,   //外部电压检测菜单编号
    Game_Menu             = 4,   //小游戏
    GamePlay_Menu        = 5,
    GameRecord_Menu      = 6,
    AuthorInfor_Menu     = 7,
}item_id_t;

//定义菜单数组数量 (注意，数组0指针位置不存放不使用，需要至少多预留一个位置)
#define ITME_AMOUNT    10

typedef struct 
{
    uint8_t hold_flag;    //之前是否一直占有菜单显示界面（便于判断是否需要清屏）
    item_id_t self_id;
    item_id_t (* fun)(uint8_t _sw_state);  //功能函数, 返回需要跳转的编号 ，为 0 则不跳转。
}menu_item_t;

static menu_item_t menu_items[ITME_AMOUNT];
static uint8_t sw_state = 0;
static item_id_t menu_item_index = Main_Menu; //!!!!!,初始指针不应该指向空(0)


static void _menu_clean(void)
{
    LCD_Fill(0, 0, 240, 135, BLACK);
}

static item_id_t _main_menu(uint8_t _sw_state)
{
    const uint8_t SUB_MENU_NUM = 4;  //实际子菜单数量
    const uint8_t head_title[] = "select function";
    const uint8_t sub_title_0[] = "power meter";
    const uint8_t sub_title_1[] = "play game";
    const uint8_t sub_title_2[] = "ex voltage";
    const uint8_t sub_title_3[] = "author infor";

    static uint8_t last_select_index;
    uint8_t select_index = last_select_index;

    if(menu_items[Main_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[Main_Menu].hold_flag = CONTINUE;
        last_select_index = 0;
        select_index = 0;

        //基本框架  
        LCD_ShowString(0, 0, head_title, WHITE, BLACK, 24, 0);
        LCD_DrawLine(0, 26, 240, 26, WHITE);
        LCD_ShowString(30, 30, sub_title_0, YELLOW, BLACK, 16, 0);
        LCD_ShowString(30, 50, sub_title_1, YELLOW, BLACK, 16, 0);
        LCD_ShowString(30, 70, sub_title_2, YELLOW, BLACK, 16, 0);
        LCD_ShowString(30, 90, sub_title_3, YELLOW, BLACK, 16, 0);
    }

    switch (_sw_state)
    {
    case LEFT_SHORT:
        if(select_index <= 0){
            select_index = SUB_MENU_NUM - 1;
        }
        else{
            select_index--;
        }
        break;
    case RIGHT_SHORT:
        if(select_index >= (SUB_MENU_NUM - 1)){
            select_index = 0;
        }
        else{
            select_index++;
        }
        break;
    case ENTER_SHORT:  //按下确定键，立即切入对应子菜单
        menu_items[Main_Menu].hold_flag = TURN_TO;  //切换菜单跳转标志
        switch (select_index)
        {
        case 0:
            return PowerMeter_Menu;        
        case 1:
            return Game_Menu;
        case 2:
            return ExternalVoltage_Menu;
        case 3:
            return AuthorInfor_Menu;
        default:
            break;
        }
    default:
        break;
    }

    //清除之前的指示符
    switch (last_select_index)
    {
    case 0:
        LCD_Fill(8, 30, 16, 46, BLACK);
        break;
    case 1:
        LCD_Fill(8, 50, 16, 66, BLACK);
    case 2:
        LCD_Fill(8, 70, 16, 86, BLACK);
    case 3:
        LCD_Fill(8, 90, 16, 106, BLACK);

    default:
        break;
    }
    //更新指示符
    switch (select_index)
    {
    case 0:
        LCD_ShowChar(8, 30, '>', RED, BLACK, 16, 0);
        break;
    case 1:
        LCD_ShowChar(8, 50, '>', RED, BLACK, 16, 0);
        break;    
    case 2:
        LCD_ShowChar(8, 70, '>', RED, BLACK, 16, 0);
        break;
    case 3:
        LCD_ShowChar(8, 90, '>', RED, BLACK, 16, 0);
        break;

    default:
        break;
    }

    last_select_index = select_index;

    return Ignore ;
}

static item_id_t _power_meter_menu(uint8_t _sw_state)
{
    const uint8_t crt_pixel_scale = 20;  //显示比例
    const uint8_t vtg_pixel_scale = 10;  //显示比例
    static double current_fifo[169]; //环形队列显示波形
    static double voltage_fifo[169];
    static uint8_t fifo_full_flag =0;
    static uint8_t fifo_head_index= 0, fifo_tail_index = 0;
    static uint16_t sample_interval = 50;   //采样间隔时间 ms

    static uint32_t first_time;
    uint32_t time;

    if(menu_items[PowerMeter_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[PowerMeter_Menu].hold_flag = CONTINUE; 
        //重置数组
        memset(voltage_fifo, 0, sizeof(voltage_fifo)/sizeof(voltage_fifo[0]));
        memset(current_fifo, 0, sizeof(current_fifo)/sizeof(current_fifo[0]));
        fifo_head_index = 0;
        fifo_tail_index = 0;
        fifo_full_flag = 0;
        first_time = DPM_ReadSysTime_Ms();

        //基本框架  
        LCD_DrawLine(170, 0, 170, 135, WHITE);
        LCD_ShowChar(227, 5, 'A', WHITE, BLACK, 24, 0);
        LCD_ShowChar(227, 39, 'V', WHITE, BLACK, 24, 0);
        LCD_ShowChar(227, 73, 'W', WHITE, BLACK, 24, 0);
        LCD_ShowChar(227, 107, 'S', WHITE, BLACK, 24, 0);

        LCD_DrawLine(0, 17, 169, 17, WHITE);
        LCD_ShowString(0, 0, "upd:", WHITE, BLACK, 16, 0);
        LCD_ShowString(57, 0, "ms", WHITE, BLACK, 16, 0);
        LCD_ShowString(88, 0, "range:", WHITE, BLACK, 16, 0);
        LCD_ShowChar(153, 0, 's', WHITE, BLACK, 16, 0);
    }
    switch (_sw_state)
    {
    case LEFT_SHORT:
            sample_interval +=50;
        break;
    case RIGHT_SHORT:
        if(sample_interval > 50){
            sample_interval -=50;
        }
        break;
    case LEFT_LONG:
            sample_interval +=200;
        break;
    case RIGHT_LONG:
        if(sample_interval > 200){
            sample_interval -=200;
        }
        break;
    case ENTER_LONG:
        menu_items[PowerMeter_Menu].hold_flag = TURN_TO;
        return  Main_Menu;

    default:
        break;
    }

    //更新数据
    current_fifo[fifo_head_index] = DPM_CurrentRead();
    voltage_fifo[fifo_head_index] = DPM_InVoltageRead();
    time = DPM_ReadSysTime_Ms();

    //显示文本数据
    LCD_ShowFloatNum1(172, 5, (float)current_fifo[fifo_head_index], 3, BLUE, BLACK, 24);
    LCD_ShowFloatNum1(172, 39, (float)voltage_fifo[fifo_head_index], 3, GREEN, BLACK, 24);
    LCD_ShowFloatNum1(172, 73, (float)(current_fifo[fifo_head_index]*voltage_fifo[fifo_head_index]), 3, RED, BLACK, 24);
    LCD_ShowIntNum(172, 107, (uint16_t)(time - first_time)/1000.0, 4, YELLOW, BLACK, 16);

    LCD_ShowIntNum(33, 0, sample_interval, 3, RED, BLACK, 16);
    LCD_ShowIntNum(137, 0, sample_interval*169/1000, 2, RED, BLACK, 16);
    //显示波形
    uint8_t temp_head_index = fifo_head_index;
    uint8_t temp_tail_index = fifo_tail_index;
    uint8_t i=0;
    //先清除第一列点
    LCD_Fill(0, 18, 1, 135, BLACK);
    while(temp_tail_index != temp_head_index)
    {
        uint8_t current_y = 0;
        uint8_t voltage_y =0;

        //清除久点  
        if(temp_tail_index > 0){
            current_y =135 - current_fifo[temp_tail_index -1] * crt_pixel_scale;
            voltage_y =135 - voltage_fifo[temp_tail_index -1] * vtg_pixel_scale;
        }else{
            current_y = 135 - (current_fifo[168] * crt_pixel_scale);
            voltage_y = 135 - (voltage_fifo[168] * vtg_pixel_scale);
        }
        if(current_y >=17 && current_y <=135){
            LCD_DrawPoint(i, current_y, BLACK);
        }
        if(voltage_y >=17 && voltage_y <=135){
            LCD_DrawPoint(i, voltage_y, BLACK);
        }    


        //补充新点
        current_y = 135 - (current_fifo[temp_tail_index] * crt_pixel_scale);
        voltage_y = 135 - (voltage_fifo[temp_tail_index] * vtg_pixel_scale);
        if(current_y >=17 && current_y <=135){
            LCD_DrawPoint(i, current_y, BLUE);           
        }
        if(voltage_y >=17 && voltage_y <=135){
            LCD_DrawPoint(i, voltage_y, GREEN);  
        } 

        //横坐标自增
        i++;
        //移动显示队列指针，第一个会被忽略
        if(temp_tail_index >= 168){
            temp_tail_index =0;
        }else{
            temp_tail_index++;
        }
    }
    
    //移动指针
    if(fifo_head_index >=168){
        fifo_head_index = 0;
        fifo_full_flag = 1;
    }
    else{
        fifo_head_index++;
    }
    //fifo满了之后才开始尾指针自增
    if(fifo_full_flag == 1){
        if(fifo_tail_index >= 168){
            fifo_tail_index = 0;
        }
        else{
            fifo_tail_index++;
        }
    }

    SysTick_Delay_Ms(sample_interval);

    return Ignore;
}

static item_id_t _ex_voltage_menu(uint8_t _sw_state)
{
    const uint8_t ex_vtg_pixel_scale = 10;  //显示比例
    static double ex_voltage_fifo[169];  //环形队列显示波形
    static uint8_t fifo_full_flag =0;
    static uint8_t fifo_head_index= 0, fifo_tail_index = 0;
    static uint16_t sample_interval = 50;   //采样间隔时间 ms

    if(menu_items[ExternalVoltage_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[ExternalVoltage_Menu].hold_flag = CONTINUE; 
        //重置数组
        memset(ex_voltage_fifo, 0, sizeof(ex_voltage_fifo)/sizeof(ex_voltage_fifo[0]));
        fifo_head_index = 0;
        fifo_tail_index = 0;
        fifo_full_flag = 0;

        //基本框架  
        LCD_DrawLine(170, 0, 170, 135, WHITE);
        // LCD_ShowChar(227, 5, 'A', WHITE, BLACK, 24, 0);
        LCD_ShowChar(227, 39, 'V', WHITE, BLACK, 24, 0);
        // LCD_ShowChar(227, 73, 'W', WHITE, BLACK, 24, 0);
        // LCD_ShowChar(227, 107, 'S', WHITE, BLACK, 24, 0);

        LCD_DrawLine(0, 17, 169, 17, WHITE);
        LCD_ShowString(0, 0, "upd:", WHITE, BLACK, 16, 0);
        LCD_ShowString(57, 0, "ms", WHITE, BLACK, 16, 0);
        LCD_ShowString(88, 0, "range:", WHITE, BLACK, 16, 0);
        LCD_ShowChar(153, 0, 's', WHITE, BLACK, 16, 0);
    }
    switch (_sw_state)
    {
    case LEFT_SHORT:
            sample_interval +=50;
        break;
    case RIGHT_SHORT:
        if(sample_interval > 50){
            sample_interval -=50;
        }
        break;
    case LEFT_LONG:
            sample_interval +=200;
        break;
    case RIGHT_LONG:
        if(sample_interval > 200){
            sample_interval -=200;
        }
        break;
    case ENTER_LONG:
        menu_items[ExternalVoltage_Menu].hold_flag = TURN_TO;
        return  Main_Menu;

    default:
        break;
    }

    //更新数据
    ex_voltage_fifo[fifo_head_index] = DPM_ExVoltageRead();

    //显示文本数据
    LCD_ShowFloatNum1(172, 39, (float)ex_voltage_fifo[fifo_head_index], 3, GREEN, BLACK, 24);

    LCD_ShowIntNum(33, 0, sample_interval, 3, RED, BLACK, 16);
    LCD_ShowIntNum(137, 0, sample_interval*169/1000, 2, RED, BLACK, 16);
    //显示波形
    uint8_t temp_head_index = fifo_head_index;
    uint8_t temp_tail_index = fifo_tail_index;
    uint8_t i=0;
    //先清除第一列点
    LCD_Fill(0, 18, 1, 135, BLACK);
    while(temp_tail_index != temp_head_index)
    {
        uint8_t ex_voltage_y =0;

        //清除久点  
        if(temp_tail_index > 0){
            ex_voltage_y =135 - ex_voltage_fifo[temp_tail_index -1] * ex_vtg_pixel_scale;
        }else{
            ex_voltage_y = 135 - (ex_voltage_fifo[168] * ex_vtg_pixel_scale);
        }
        if(ex_voltage_y >=17 && ex_voltage_y <=135){
            LCD_DrawPoint(i, ex_voltage_y, BLACK);
        }    


        //补充新点
        ex_voltage_y = 135 - (ex_voltage_fifo[temp_tail_index] * ex_vtg_pixel_scale);
        if(ex_voltage_y >=17 && ex_voltage_y <=135){
            LCD_DrawPoint(i, ex_voltage_y, GREEN);  
        } 

        //横坐标自增
        i++;
        //移动显示队列指针，第一个会被忽略
        if(temp_tail_index >= 168){
            temp_tail_index =0;
        }else{
            temp_tail_index++;
        }
    }
    
    //移动指针
    if(fifo_head_index >=168){
        fifo_head_index = 0;
        fifo_full_flag = 1;
    }
    else{
        fifo_head_index++;
    }
    //fifo满了之后才开始尾指针自增
    if(fifo_full_flag == 1){
        if(fifo_tail_index >= 168){
            fifo_tail_index = 0;
        }
        else{
            fifo_tail_index++;
        }
    }

    SysTick_Delay_Ms(sample_interval);

    return Ignore;
}

static item_id_t _game_menu(uint8_t _sw_state)
{
    const uint8_t SUB_MENU_NUM = 2;  //实际子菜单数量
    const uint8_t head_title[] = "dinosaur game";
    const uint8_t sub_title_0[] = "play";
    const uint8_t sub_title_1[] = "record";

    static uint8_t last_select_index;
    uint8_t select_index = last_select_index;

    if(menu_items[Game_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[Game_Menu].hold_flag = CONTINUE;
        last_select_index = 0;
        select_index = 0;

        //基本框架  
        LCD_ShowString(42, 0, head_title, WHITE, BLACK, 24, 0);
        LCD_DrawLine(0, 26, 240, 26, WHITE);
        LCD_ShowString(74, 45, sub_title_0, YELLOW, BLACK, 24, 0);
        LCD_ShowString(74, 75, sub_title_1, YELLOW, BLACK, 24, 0);
    }

    switch (_sw_state)
    {
    case LEFT_SHORT:
        if(select_index <= 0){
            select_index = SUB_MENU_NUM - 1;
        }
        else{
            select_index--;
        }
        break;
    case RIGHT_SHORT:
        if(select_index >= (SUB_MENU_NUM - 1)){
            select_index = 0;
        }
        else{
            select_index++;
        }
        break;
    case ENTER_SHORT:  //按下确定键，立即切入对应子菜单
        menu_items[Game_Menu].hold_flag = TURN_TO;  //切换菜单跳转标志
        switch (select_index)
        {
        case 0:
            return GamePlay_Menu;
        case 1:
            return GameRecord_Menu;
        default:
            break;
        }
    case ENTER_LONG:  //长按退出
        menu_items[Game_Menu].hold_flag = TURN_TO;  //切换菜单跳转标志
        return Main_Menu;
    default:
        break;
    }

    //清除之前的指示符
    switch (last_select_index)
    {
    case 0:
        LCD_Fill(58, 45, 58+13, 45+25, BLACK);
        break;
    case 1:
        LCD_Fill(58, 75, 58+13, 75+25, BLACK);

    default:
        break;
    }
    //更新指示符
    switch (select_index)
    {
    case 0:
        LCD_ShowChar(58, 45, '>', RED, BLACK, 24, 0);
        break;
    case 1:
        LCD_ShowChar(58, 75, '>', RED, BLACK, 24, 0);
        break;    

    default:
        break;
    }

    last_select_index = select_index;

    return Ignore ;    
}

static item_id_t _game_record_menu(uint8_t _sw_state)
{
    if(menu_items[GameRecord_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[GameRecord_Menu].hold_flag = CONTINUE;

        DPM_ShowScoreRecords();
    }

    switch (_sw_state)
    {
    case ENTER_LONG:  //按下确定键，立即切入对应子菜单
        menu_items[GameRecord_Menu].hold_flag = TURN_TO;  //切换菜单跳转标志
        return Game_Menu;
    default:
        break;
    }

    return Ignore ;    
}

static item_id_t _game_play_menu(uint8_t _sw_state)
{
    if(menu_items[GamePlay_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[GamePlay_Menu].hold_flag = CONTINUE;

        DPM_DinoGame(GAME_RESET);
    }

    switch (_sw_state)
    {
    case LEFT_SHORT:
        DPM_DinoGame(GAME_RESET);
        break;
    case RIGHT_SHORT:
        DPM_DinoGame(DINO_JUMP);
        break;
    case ENTER_LONG:  //长按退出
        menu_items[GamePlay_Menu].hold_flag = TURN_TO;  //切换菜单跳转标志
        return Game_Menu;
    default:
        DPM_DinoGame(0);
        break;
    }

    return Ignore ;   
}

static item_id_t _author_infor_menu(uint8_t _sw_state)
{
    if(menu_items[AuthorInfor_Menu].hold_flag == TURN_TO)
    {
        _menu_clean();
        menu_items[AuthorInfor_Menu].hold_flag = CONTINUE;

        //显示作者信息
        LCD_ShowString(0, 0, "copyright: DeadPoem", RED, BLACK, 24, 0);
        LCD_ShowString(0, 28, "QQ: 2819731924", GREEN, BLACK, 24, 0);
        LCD_ShowString(0, 56, "version: v0.1", WHITE, BLACK, 24, 0);
        LCD_ShowString(0, 84, "time: 2022/8/26", YELLOW, BLACK, 24, 0);
    }

    switch (_sw_state)
    {
    case ENTER_LONG:  //按下确定键，立即切入对应子菜单
        menu_items[AuthorInfor_Menu].hold_flag = TURN_TO;  //切换菜单跳转标志
        return Main_Menu;
    default:
        break;
    }

    return Ignore ;  
}

//菜单初始化，将菜单函数存放在数组相应位置中
void DPM_MenuInit(void)
{
    menu_item_t menu_item;

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = Main_Menu;
    menu_item.fun = _main_menu;
    menu_items[menu_item.self_id] = menu_item;

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = PowerMeter_Menu;
    menu_item.fun = _power_meter_menu;
    menu_items[menu_item.self_id] = menu_item;

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = ExternalVoltage_Menu;
    menu_item.fun = _ex_voltage_menu;
    menu_items[menu_item.self_id] = menu_item;  

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = Game_Menu;
    menu_item.fun = _game_menu;
    menu_items[menu_item.self_id] = menu_item;  

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = GameRecord_Menu;
    menu_item.fun = _game_record_menu;
    menu_items[menu_item.self_id] = menu_item; 

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = GamePlay_Menu;
    menu_item.fun = _game_play_menu;
    menu_items[menu_item.self_id] = menu_item;   

    menu_item.hold_flag = TURN_TO;
    menu_item.self_id = AuthorInfor_Menu;
    menu_item.fun = _author_infor_menu;
    menu_items[menu_item.self_id] = menu_item;  
}

void DPM_MenuCmd(void)
{
    item_id_t jump_id = Ignore;
    sw_state = DPM_SwInforRead();

    jump_id = menu_items[menu_item_index].fun(sw_state); 
    if(jump_id != Ignore)  //不为0才是有效跳转菜单指令
    {
        menu_item_index = jump_id;
    }
}

